package cn.sx10.dao;

import cn.sx10.dao.ubils.FieldAnnotition;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

//它帮我完成SQL语句的操作（基础）
public class BaseDao {
     //存放所有连接相关
    static String driver;
    static String url;
    static String user;
    static String password;

     //数据库连接池对象
    static DataSource dataSource;
     //加载驱动
    static {
        //读取配置文件
         Properties properties=new Properties();
         try
                 (InputStream inputStream = BaseDao.class.getClassLoader().getResourceAsStream("database.properties");)
         {
             //读取配置文件
             properties.load(inputStream);
             //工厂装配数据源
             dataSource=  BasicDataSourceFactory.createDataSource(properties);
          } catch (Exception e) {
             e.printStackTrace();
         }

    }
    //获取连接对象
    public Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
   //释放所有资源
    public   void closeConnection(Connection connection, Statement statement){
        //使用的资源要释放：严格的顺序要求：resultset -->statement-->connection
        try {
            if(statement != null){ statement.close();}
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if(connection != null){ connection.close();}
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }
    //释放资源--通过Result
    public  void closeResult(ResultSet resultSet) throws SQLException {
        //通过resultset获取执行对象，连接对象
        Statement statement= resultSet.getStatement();
        Connection connection = statement.getConnection();
        try {
            if(resultSet != null){ resultSet.close();}
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if(statement != null){ statement.close();}
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if(connection != null){ connection.close();}
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }


    //执行：增、删、改
    public int insertUpdateDelete(String sql,Object... parms){
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            //获取连接对象
            connection  = this.getConnection();
            //创建执行对象
            statement  = connection.prepareStatement(sql);
            if (parms !=null){
                for (int i = 0; i < parms.length; i++) {
                    statement.setObject((i+1),parms[i]);
                }
            }

            //执行sql
            return statement.executeUpdate();

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            //关闭资源
            this.closeConnection(connection,statement);
        }

        return  -1;
    }
    //执行：查
    public ResultSet query(String sql,Object... parms) throws SQLException {
        //返回声明类型呢？---我们不处理，交给取数据的人自己处理

            //获取连接对象
            Connection  connection  = this.getConnection();
            //创建执行对象
           PreparedStatement statement  = connection.prepareStatement(sql);
           if (parms !=null){
               for (int i = 0; i < parms.length; i++) {
                   statement.setObject((i+1),parms[i]);
               }
           }
            //执行sql
            return  statement.executeQuery();

        /*此时：因为将结果集交给外部处理，所有：
                1、 不能当前方法中关闭连接
                2、外部必须要关闭
         */
//        finally {
//            //关闭资源
//            this.closeConnection(connection,statement,resultSet);
//        }

    }
    //执行：查 --- 单个对象
    public <T>  T queryToSingle(Class<T>  tagClass,  String sql,Object... parms)  {

        //获取连接对象
        ResultSet resultSet=null;
        try
        {
            Connection connection  = this.getConnection();
            //创建执行对象
            PreparedStatement statement = connection.prepareStatement(sql);
            if (parms != null) {
                for (int i = 0; i < parms.length; i++) {
                    statement.setObject((i + 1), parms[i]);
                }
            }
            //执行sql
            resultSet = statement.executeQuery();
            //-----------封装读取过程--------
            //创建实体
            T target = tagClass.newInstance();
            if (resultSet.next()) {
                //字段   --->  属性：赋值？？？？？？？
                //问题：SQL查询哪张表？字段？实体属性？
//            user.setName(resultSet.getInt("字段名"))
                //反射处目标对象的所有属性
               Field[]  fields= tagClass.getDeclaredFields();
                for (Field field: fields) {
                    field.setAccessible(true); //该属性设置为可赋值状态

                    //获取属性名
                    String columnName = field.getName();
                    //判断该属性，是否贴有您自己注解--------------------
                    FieldAnnotition fieldAnnotition= field.getAnnotation(FieldAnnotition.class);
                    if (fieldAnnotition != null){
                        //从注解类中，获取携带的“数据库字段名”
                        columnName = fieldAnnotition.columnName();
                    }
                    //-----------------------------------------------------------
                    field.set(target,resultSet.getObject(columnName));
                }
                return  target;

            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            try {
                this.closeResult(resultSet);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        return  null;
    }
    //执行：查 --- 多个对象
    public <T> List<T> queryToList(Class<T>  tagClass,String sql, Object... parms){
        List<T> targetList = new ArrayList<>() ;
        //获取连接对象
        ResultSet resultSet=null;
        try
        {
            Connection connection  = this.getConnection();
            //创建执行对象
            PreparedStatement statement = connection.prepareStatement(sql);
            if (parms != null) {
                for (int i = 0; i < parms.length; i++) {
                    statement.setObject((i + 1), parms[i]);
                }
            }
            //执行sql
            resultSet = statement.executeQuery();
            //-----------封装读取过程--------
            //创建实体
            while (resultSet.next()) {
                T target = tagClass.newInstance();
                Field[]  fields= tagClass.getDeclaredFields();
                for (Field field: fields) {
                    field.setAccessible(true); //该属性设置为可赋值状态
                    String columnName = field.getName();
                     //判断该属性，是否贴有您自己注解--------------------
                    FieldAnnotition fieldAnnotition= field.getAnnotation(FieldAnnotition.class);
                    if (fieldAnnotition != null){
                        columnName = fieldAnnotition.columnName();
                    }
                    //-----------------------------------------------------------
                    field.set(target,resultSet.getObject(columnName));
                }
                targetList.add(target);

            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            try {
                this.closeResult(resultSet);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        return  targetList;
    }


}
